package com.education.business.service.system;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.education.business.mapper.SystemAdminMapper;
import com.education.business.service.BaseService;
import com.education.common.exception.BusinessException;
import com.education.common.model.PageInfo;
import com.education.common.util.Md5Utils;
import com.education.common.util.ObjectUtils;
import com.education.common.util.Result;
import com.education.common.util.ResultCode;
import com.education.model.dto.AdminRoleDto;
import com.education.model.dto.AdminUserSession;
import com.education.model.dto.MenuTree;
import com.education.model.entity.SystemAdmin;
import com.education.model.entity.SystemAdminRole;
import com.education.model.entity.SystemMenu;
import com.education.model.entity.SystemRole;
import com.education.model.request.PageParam;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author 余一
 * @date 2021/9/17  15:44
 */
@Service
public class SystemAdminService extends BaseService<SystemAdminMapper, SystemAdmin> {

    @Autowired
    private SystemMenuService systemMenuService;
    @Autowired
    private SystemRoleService systemRoleService;
    @Autowired
    private SystemAdminRoleService systemAdminRoleService;

    public Result login(String userName,String password){
        Result result = new Result();
        Subject subject = SecurityUtils.getSubject();
        UsernamePasswordToken token = new UsernamePasswordToken(userName, password);
        try{
            subject.login(token);
            result.setCode(ResultCode.SUCCESS);
            result.setMessage("登录成功");
        }catch (Exception e){
            logger.error("登录失败",e);
            result.setCode(ResultCode.FAIL);
            if (e instanceof UnknownAccountException) {
                result.setMessage("用户不存在");
            }else {
                result.setMessage("用户名或密码错误");
            }
        }
        return result;
    }


    /**
     * 加载用户菜单及权限标识
     * @param adminUserSession
     */
    public void loadUserMenuAndPermission(AdminUserSession adminUserSession) {
        List<SystemMenu> menuList = null;
        if (adminUserSession.isSuperAdmin()) {
           menuList =  systemMenuService.list(Wrappers.lambdaQuery(SystemMenu.class).orderByAsc(SystemMenu :: getSort));
        }else {
            //1.获取用户id
            Integer adminId = adminUserSession.getAdminId();
            //2.根据用户id获取对应的角色信息
            List<SystemRole> systemRoleList = systemRoleService.getRoleListByAdminId(adminId);
            //3.遍历角色集合获取角色id，装到集合容器中
            List<Integer> roleIds = systemRoleList.stream()
                    .map(SystemRole :: getId)
                    .collect(Collectors.toList());
            //4.根据角色id集合信息获取对应的权限菜单
            menuList = systemMenuService.getMenuListByRoleIds(roleIds);
        }
        if (ObjectUtils.isNotEmpty(menuList)) {
            Set<String> permissionList = menuList.stream()
                    .filter(systemMenu -> ObjectUtils.isNotEmpty(systemMenu.getPermission()))
                    .map(SystemMenu :: getPermission)
                    .collect(Collectors.toSet());
            List<MenuTree> menuTreeList = systemMenuService.getTreeMenuList(menuList);
            adminUserSession.setPermissionList(permissionList);
            adminUserSession.setMenuTreeList(menuTreeList);
        }
    }


    public PageInfo<SystemAdmin> listPage(PageParam pageParam, SystemAdmin systemAdmin) {
        Page<SystemAdmin> page = new Page<>(pageParam.getPageNumber(), pageParam.getPageSize());
        LambdaQueryWrapper<SystemAdmin> wrapper = Wrappers.<SystemAdmin>lambdaQuery()
                .like(ObjectUtils.isNotEmpty(systemAdmin.getLoginName()),
                        SystemAdmin::getLoginName,systemAdmin.getLoginName());
        return selectPage(super.page(page,wrapper));
    }


    public AdminRoleDto selectById(Integer id) {
        return baseMapper.selectById(id);
    }

    @Transactional
    public Result deleteById(Integer id){
        SystemAdmin systemAdmin = super.getById(id);
        if (systemAdmin.isSupper()) {
            return Result.fail(ResultCode.FAIL,"不允许删除超级管理员");
        }
        super.removeById(id);
        systemAdminRoleService.deleteByAdminId(id);
        return Result.success(ResultCode.SUCCESS,"删除管理员" + systemAdmin.getLoginName() + "成功");
    }

    @Transactional
    public void saveOrUpdate(AdminRoleDto adminRoleDto){

        if (ObjectUtils.isEmpty(adminRoleDto.getId())) {
            String password = adminRoleDto.getPassword();
            if (ObjectUtils.isEmpty(password)) {
                throw new BusinessException(new ResultCode(ResultCode.FAIL,"请输入密码"));
            }
            String confirmPassword = adminRoleDto.getConfirmPassword();
            if (!password.equals(confirmPassword)) {
                throw new BusinessException(new ResultCode(ResultCode.FAIL,"密码和确认密码不一致"));
            }
            String encodeSalt = Md5Utils.encodeSalt(Md5Utils.generatorKey());
            adminRoleDto.setEncrypt(encodeSalt);
            password = Md5Utils.getMd5(password, encodeSalt);
            adminRoleDto.setPassword(password);
        }

        super.saveOrUpdate(adminRoleDto);
        //保存管理员角色信息
        if (ObjectUtils.isNotEmpty(adminRoleDto.getRoleIds())) {
            List<SystemAdminRole> adminRoleList = new ArrayList<>();
            adminRoleDto.getRoleIds().forEach(roleId -> {
                SystemAdminRole systemAdminRole = new SystemAdminRole();
                systemAdminRole.setAdminId(adminRoleDto.getId());
                systemAdminRole.setRoleId(roleId);
                adminRoleList.add(systemAdminRole);
            });
            systemAdminRoleService.deleteByAdminId(adminRoleDto.getId());
            systemAdminRoleService.saveBatch(adminRoleList);
        }
    }

    /**
     * 重置密码
     * @param adminRoleDto
     */
    public void updatePassword(AdminRoleDto adminRoleDto){
        String password = adminRoleDto.getPassword();
        String newPassword = adminRoleDto.getNewPassword();
        String confirmPassword = adminRoleDto.getConfirmPassword();
        SystemAdmin systemAdmin = super.getById(adminRoleDto.getId());
        String encrypt = systemAdmin.getEncrypt();
        if (!newPassword.equals(confirmPassword)) {
            throw new BusinessException(new ResultCode(ResultCode.FAIL,"密码与确认密码不一致"));
        }


        if (ObjectUtils.isNotEmpty(password)) {
            password = Md5Utils.getMd5(password, encrypt);
            String adminPassword = systemAdmin.getPassword();
            if (!adminPassword.equals(password)) {
                throw new BusinessException(new ResultCode(ResultCode.FAIL,"密码输入错误"));
            }
        }

        password = Md5Utils.getMd5(newPassword,encrypt);
        UpdateWrapper updateWrapper = new UpdateWrapper();
        updateWrapper.set("password",password);
        updateWrapper.eq("id",adminRoleDto.getId());
        super.update(updateWrapper);
    }
}
